package bz.ziro.kanbe.bean;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Logger;

import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.mail.util.ByteArrayDataSource;

/**
 * メールデータ
 * @author Administrator
 */
public class MailData {

    //@SuppressWarnings("unused")
    private static final Logger logger = Logger.getLogger(MailData.class.getName());
    
    /**
     * タイトル
     */
	private String subject;
	/**
	 * 内容
	 */
	private String text;

	/**
	 * 送信者
	 */
	private List<String> fromAddress;
	
	/**
	 * 受信者
	 */
	private List<String> toAddress;
	
	/**
	 * ファイル名称
	 */
	private String fileName;
	/**
	 * ファイルの拡張子
	 */
	private String fileType;
	/**
	 * ファイルデータ
	 */
	private byte[] fileData = null;

	/**
	 * メールのエンコード
	 */
	private static final String ENCODE = "JISAutoDetect";
	/**
	 * メールのデコード
	 */
	private static final String DECODE = "ISO-2022-JP";

	/**
	 * コンストラクタ
	 * @param aMessage
	 */
	public MailData(MimeMessage aMessage) {
		try {
		
			//アドレスデータを取得する
			fromAddress = new ArrayList<String>();
			toAddress   = new ArrayList<String>();
		
			Enumeration<?> enu = aMessage.getAllHeaderLines();
			//データ数回繰り返す
			while ( enu.hasMoreElements() ) {
				String line = (String)enu.nextElement();
				if ( line.toLowerCase().indexOf("from") >= 0 ) {
					//fromを検索して追加
					fromAddress.add(line);
				} else if ( line.toLowerCase().indexOf("to") >= 0 ) {
					//toを検索して追加
					toAddress.add(line);
				}
			}
			
			//タイトルを取得する
			String wkSub = aMessage.getSubject();
			setSubject(MimeUtility.decodeText(wkSub));
			//解析を行う
			analysisPart(aMessage);
        } catch (MessagingException e) {
        	logger.warning(e.getMessage());
        } catch (Exception e) {
        	logger.warning(e.getMessage());
        }
	}

    /**
     * メール解析
     *
     * @param part
     * @throws Exception
     */
    private void analysisPart(Part part) throws Exception {

        if (part.isMimeType("multipart/*")) {
			
            ByteArrayDataSource byteArrayDataSource = new ByteArrayDataSource(
                    (InputStream) part.getContent(), part.getContentType());
            Multipart content = new MimeMultipart(byteArrayDataSource);

            // 含まれるパートを再帰的に処理
            int count = content.getCount();
            //データ回数繰り返す
            for (int cnt = 0; cnt < count; cnt++) {
            	analysisPart(content.getBodyPart(cnt));
            }
        } else if (part.isMimeType("text/plain")) {
        	
            InputStream is = (InputStream) part.getInputStream();

            Reader reader = new InputStreamReader(is);
            BufferedReader bufReader = new BufferedReader(reader);
            StringBuilder sb = new StringBuilder();
          
            //改行数回繰り返す
            for (String line; (line = bufReader.readLine()) != null;) {
                sb.append(new String(line.getBytes(DECODE),ENCODE)+ "\n");
            }
            //テキストファイルを作成
            setText(sb.toString());

        } else {
        	//データを取得
        	byte[] bytes = getAttachments(part);
        	//取得できてた場合
        	if ( bytes != null ) {
        		//添付ファイルを作成
        		setFileData(bytes);
        	}
        }
    }

    /**
     * 添付ファイルを取得
     *
     * @param part
     * @throws MessagingException
     * @throws IOException
     */
    private byte[] getAttachments(Part part) throws MessagingException, IOException {

        String disp = part.getDisposition();
        //添付ファイルの場合
        if (disp == null || disp.equalsIgnoreCase(Part.ATTACHMENT)) {
        	
        	//HTMLの場合
            if (part.isMimeType("text/html")) {
            	//無視して大丈夫でしょう・・・多分
            	return null;
            }

        	String encodeFileName = part.getFileName();
        	if ( encodeFileName != null ) {
        		fileName =  MimeUtility.decodeText(part.getFileName());
        		setFileType("");
        		int idx = fileName.lastIndexOf(".");
        		if ( idx >= 0 ) {
        			setFileType(fileName.substring(idx));
        		}
        	}
        	//ファイルの内容をバイトデータにして返す
            return generateFileData(part.getInputStream());
        }
        return null;
    }

    /**
     * バイトデータの取得
     * @param in
     * @return Blob
     * @throws IOException
     */
    private byte[] generateFileData(InputStream in) throws IOException{
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int len;
        byte[] buffer = new byte[1024];
        while ( (len = in.read(buffer, 0, buffer.length)) != -1) {
            out.write(buffer, 0, len);
        }
        byte[] bytes = out.toByteArray();
        return bytes;
    }
    

	/**
	 * @param subject the subject to set
	 */
	public void setSubject(String subject) {
		this.subject = subject;
	}

	/**
	 * @return the subject
	 */
	public String getSubject() {
		return subject;
	}

	/**
	 * @param text the text to set
	 */
	public void setText(String text) {
		this.text = text;
	}

	/**
	 * @return the text
	 */
	public String getText() {
		return text;
	}

	/**
	 * @param fileType the fileType to set
	 */
	public void setFileType(String fileType) {
		this.fileType = fileType;
	}

	/**
	 * @return the fileType
	 */
	public String getFileType() {
		return fileType;
	}

	/**
	 * @param fileData the fileData to set
	 */
	public void setFileData(byte[] fileData) {
		this.fileData = fileData;
	}

	/**
	 * @return the fileData
	 */
	public byte[] getFileData() {
		return fileData;
	}

	@Override
	public String toString() {
	
		String buf = "タイトル：" + subject + "\n";

		//送信候補数回回す
		for ( String from : fromAddress ) {
			buf += ("From:" + from + "\n");
		}
		//受信候補数回回す
		for ( String to : toAddress ) {
			buf += ("To:" + to + "\n");
		}
	
		//ファイルデータが存在した場合
		if ( fileData != null ) {
			buf += ("添付あり\n");
			buf += ("名前:" + fileName + "\n");
			buf += ("拡張子:" + fileType + "\n");
		} else {
			buf += ("添付なし\n");
		}
		
		//内容を表示
        buf += ("内容:" + text);
		return buf;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public List<String> getFromAddress() {
		return fromAddress;
	}

	public void setFromAddress(List<String> fromAddress) {
		this.fromAddress = fromAddress;
	}

	public List<String> getToAddress() {
		return toAddress;
	}

	public void setToAddress(List<String> toAddress) {
		this.toAddress = toAddress;
	}
}
